package com.foreveross.proxyip.core.pools.thread;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import com.foreveross.proxyip.core.pools.AvailablePool;
import com.foreveross.proxyip.core.pools.DbPool;
import com.foreveross.proxyip.core.pools.PoolsManager;
import com.foreveross.proxyip.core.pools.validate.TestProxyIp;
import com.foreveross.proxyip.core.redis.RedisExecutor;
import com.foreveross.proxyip.entity.ProxyIpBean;
import com.foreveross.proxyip.exception.ProxyIpServiceException;
import com.foreveross.proxyip.infra.base.ddd.repository.IBaseRepository;
import com.foreveross.proxyip.util.SerializeUtil;

/**
 * 池的检出线程类
 * 
 * @author lyq
 * 
 */
@SuppressWarnings("rawtypes")
public class CheckOutValidateThread implements Callable {
	protected static final Logger log = Logger.getLogger(PoolsManager.class);
	private List tempIpList = null;
	IBaseRepository repository = null;// 提供jpa数据库操作的支持
	AvailablePool pool = null;

	public CheckOutValidateThread(List tempIpList, AvailablePool pool,
			IBaseRepository repository) {
		this.tempIpList = tempIpList;
		this.repository = repository;
		this.pool = pool;
	}

	@SuppressWarnings("unchecked")
	public Object call() {
		List<ProxyIpBean> historyList = new ArrayList();
		List retrieveList = new ArrayList();
		try {
			for (int i = 0; i < tempIpList.size(); i++) {
				ProxyIpBean bean = null;
				boolean disabledBean = false;
				try {
					final String ip = (String) tempIpList.get(i);
					
					if (ip == null) {
						continue;
					}
					
					bean = (ProxyIpBean) this.pool.ipStoreMap.get(ip);

					if (bean == null) {
						this.pool.poolIpMap.remove(ip);
						pool.removeMarkIpAlreadyUsed(ip);
						continue;
					}

					if (this.pool.isIpLock(ip)) {
						continue;
					}

					TestProxyIp t = pool.getValidate();
					int vali = t.validate(bean, 2);

					if (vali != 0) {
						// RetrieveIpEntity entity = bean.toRetrieveIpEntity();
						// entity.setCreateTime(new Date());
						// entity.setId(null);
						// entity.setRetrieveChannel(pool.poolSign);
						retrieveList.add(bean);

						// BufferInstance bufferinstance = new
						// BufferInstance(entity, Operations.CREATE);
						// BufferCacheManager.getInstance().excure(bufferinstance,"retrieve");
					} else if (vali == 0) {
						// HistoryIpEntity entity = bean.toHistoryIpEntity();
						// entity.setCreateTime(new Date());
						// entity.setId(null);
						// entity.setRetrieveChannel(pool.poolSign);
						historyList.add(bean);

						// BufferInstance bufferinstance = new
						// BufferInstance(entity, Operations.CREATE);
						// BufferCacheManager.getInstance().excure(bufferinstance,"history");
						if (pool.contains(bean.getCompletionIP())) {
							disabledBean = true;
							Set<String> using = bean.getUsingKeys();
							using.remove(this.pool.poolSign);
						}
					}
					
					if (bean != null && StringUtils.isNotBlank(bean.getCompletionIP())) {
						int update = this.pool.beforeUpdate(bean);

						final int _update = update, _vali = vali;
						final boolean _disabledBean = disabledBean;
						final ProxyIpBean _bean = bean;

						new RedisExecutor<Long>() {
							int update = _update, vali = _vali;
							boolean disabledBean = _disabledBean;
							ProxyIpBean bean = _bean;

							@Override
							public Long run() throws Exception {
								// 验证结果要保存到redis
								tran = jedis.multi();
								if (disabledBean) {
									removeIpTime(bean);
									bean.getIp2ChannelTime().remove(pool.poolSign);
									pool.addIpOutChannelTime(bean);
								}
								
								if (update == 1 || (vali == 1 && DbPool.POOL_CODE.equals(pool.poolSign))) {
									bean.setCheckTime(System.currentTimeMillis());
									tran.set(bean.getCompletionIP().getBytes(), SerializeUtil.serialize(bean));// 覆盖，不用成为僵尸了。
									tran.expire(bean.getCompletionIP().getBytes(), 3600000);
								} else if (update == 0) {
									tran.del(bean.getCompletionIP().getBytes());
								}
								if (vali == 0) {
									pool.remove(tran, bean);
								}

								tran.exec();
								return null;
							}
						}.exec();
						
						// 如果要删除的则同时也把标记删除
						if (_update == 0 || vali == 0) {
							pool.removeMarkIpAlreadyUsed(bean.getCompletionIP());
						}
					}

				} catch (Exception e) {
					ProxyIpServiceException.getStackTrace(e);
				} finally {
					if (bean != null) {
						this.pool.unIpLock(bean.getCompletionIP());
						// lock.unlock();
					}
				}
			}

		} catch (Exception e) {
			log.error(ProxyIpServiceException.getStackTrace(e));
			e.printStackTrace();
		} finally {
			tempIpList.clear();
			historyList.clear();
			retrieveList.clear();
		}
		
		return null;
	}

	/**
	 * 删除ip标记的时间
	 * 
	 * @param proxyIp
	 */
	private void removeIpTime(ProxyIpBean proxyIp) {
		Map vliTime = proxyIp.getChannelVliTime();
		if (vliTime.get(pool.poolSign) != null) {
			vliTime.remove(pool.poolSign);
		}
		Map intoTime = proxyIp.getIp2ChannelTime();
		if (intoTime.get(pool.poolSign) != null) {
			intoTime.remove(pool.poolSign);
		}
		// Map outTime = proxyIp.getIpOutChannelTime();
		// if(outTime.get(pool.poolSign)!=null){
		// outTime.remove(pool.poolSign);
		// }
	}
}
